package hehe.worker.pool;

import hehe.worker.base.Pool;
import hehe.worker.base.Queue;
import hehe.worker.base.Task;
import hehe.worker.base.Worker;
import hehe.worker.queue.LinkedBlockingTaskQueue;
import java.util.HashSet;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


/**
 * worker 任务池
 *<B>说明：</B>
 *<pre>
 * 类似线程池
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  示例:创建一个固定线程池
 *  ```java
 *  Pool workerTaskPool =  WorkerExecutors.newFixedWorkerPool(4);
 *   workerTaskPool.pull(new Runnable(){
         public void  run()
         {
            System.out.println("result:" + Math.random()+ ",thread no:" +  Thread.currentThread().getId());
         };
     });
 *
 *  ```
 *
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class WorkerPool extends Pool
{
    /**
     * 默认启用的worker数量
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected int defaultWorkerSize = 0;

    /**
     * 最大启用的worker 数量
     *<B>说明：</B>
     *<pre>
     *　略
     *</pre>
     */
    protected int maxWorkerSize = 0;

    /**
     * 监控线程
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    private Thread monitorThread;

    /**
     * 任务队列
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    private Queue<Runnable> taskQueue = new LinkedBlockingTaskQueue();

    /**
     * 默认任务队列大小
     *<B>说明：</B>
     *<pre>
     * 0 表示不限制
     *</pre>
     */
    protected int defaultTaskSize = 0;

    /**
     * 空闲worker 队列
     *<B>说明：</B>
     *<pre>
     *  只有默认worker 才会进入队列
     *</pre>
     */
    private Queue<Worker> freeWorkerQueue = new LinkedBlockingTaskQueue();

    /**
     * 临时worker
     *<B>说明：</B>
     *<pre>
     *  worker 启动完成后,直接删除
     *</pre>
     */
    private Queue<Worker> tempWorkerQueue = new LinkedBlockingTaskQueue();

    /**
     * 任务worker列表
     *<B>说明：</B>
     *<pre>
     *  线程worker
     *</pre>
     */
    private HashSet<Worker> workers = new HashSet<>();

    /**
     * 是否常驻进程
     *<B>说明：</B>
     *<pre>
     *  一般用于非容器类脚本
     *</pre>
     */
    private boolean daemon = false;

    public WorkerPool()
    {

    }

    public WorkerPool(int defaultWorkerSize,int maxWorkerSize)
    {
        this.defaultWorkerSize = defaultWorkerSize;
        this.maxWorkerSize = maxWorkerSize;
    }

    public void shutdown()
    {

    }

    public boolean isShutdown()
    {
        return true;
    }

    public void pull(Runnable task)
    {
        Worker worker;
        // 是否有空闲worker
        worker = this.getFreeWorker();
        if (worker != null) {
            worker.start(task);
            return ;
        }

        // 任务队列是否超出最大值
        int taskSize = this.getTaskCount();
        if (this.defaultTaskSize != 0 && taskSize >= this.defaultTaskSize) {
            // 超过默认任务队列数量,启用拒接机制
            return ;
        }

        // 判断是否需要启用新 worker 处理当前任务
        int workerSize = this.getWorkerCount();
        if (workerSize < this.maxWorkerSize ) {
            worker = this.newWorker(false);
            worker.start(task);
            return ;
        }

        // 直接压入队列,等待处理
        this.taskQueue.push(task);
        return ;
    }

    /**
     * 新建worker
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Worker newWorker(boolean defaultWorker)
    {
        Worker worker = new Worker(this.taskQueue,defaultWorker);
        this.workers.add(worker);
        worker.setWorkerPool(this);

        return worker;
    }

    /**
     * 监控线程入口
     *<B>说明：</B>
     *<pre>
     *
     *</pre>
     */
    public void run()
    {
        // 启动worker 线程
        this.process();
    }

    protected void monitor()
    {
        for (;;) {
            // 检查worker 任务是否已完成

            // 检查worker 是否已休眠
            //

        }
    }

    /**
     * 创建worker
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected void forkWorkers()
    {
        for (int i = 0; i < this.defaultWorkerSize;i++) {
            Worker worker = this.newWorker(true);
            this.tempWorkerQueue.push(worker);
        }
    }

    /**
     * 启动worker
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected void startWorkers()
    {
        Worker worker;
        while ((worker = this.tempWorkerQueue.pop()) != null) {
            worker.start();
        }
    }

    protected int getWorkerCount()
    {
        return this.workers.size();
    }

    protected int getTaskCount()
    {
        return this.taskQueue.size();
    }

    /**
     * worker 启动流程
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void process()
    {
        // 创建worker
        this.forkWorkers();

        // 启动worker
        this.startWorkers();

        if (this.daemon) {
            this.monitor();
        }
    }


    /**
     * worker启动入口
     *<B>说明：</B>
     *<pre>
     *  实例化后调用
     *</pre>
     */
    public void start()
    {
        if (this.daemon) {
            this.monitorThread = Executors.defaultThreadFactory().newThread(this);
            this.monitorThread.start();
            return;
        }

        this.process();
    }

    /**
     * worker 退出处理事件
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void workerExitEvent(Worker worker)
    {
        // 判断是否需要删除当前worker,如果
        if (worker.isDefaultWorker()) {
            this.freeWorkerQueue.push(worker);
        } else {
            // 非默认worker,运行结束后,直接删除
            this.workers.remove(worker);
        }

    }

    /**
     * 获取空闲worker
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Worker getFreeWorker()
    {
        return this.freeWorkerQueue.pop();
    }
}
